package com.binhthuan.catechist.server.service;

import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.binhthuan.catechist.server.bus.AccountBUS;
import com.binhthuan.catechist.server.domain.Account;
import com.binhthuan.catechist.server.util.JsonConverter;
import com.binhthuan.catechist.shared.constant.Action;
import com.binhthuan.catechist.shared.constant.ApplicationConstants;
import com.binhthuan.catechist.shared.constant.Parameter;
import com.binhthuan.catechist.shared.session.UserSession;

/**
 * @author Giang Đinh - Servlet phụ trách chứng thực người dùng.
 * 
 */
public class AuthenticationServlet extends AbstractServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 5177585096904153571L;

    @Override
    public void init(ServletConfig config) throws ServletException {
        /*
         * String log4jLocation =
         * config.getInitParameter("log4j-properties-location");
         * 
         * ServletContext sc = config.getServletContext();
         * 
         * if (log4jLocation == null) {System.err.println(
         * "*** No log4j-properties-location init param, so initializing log4j with BasicConfigurator"
         * ); BasicConfigurator.configure(); } else { String log4jProp =
         * sc.getRealPath(log4jLocation); File log4jFile = new File(log4jProp);
         * if (log4jFile.exists()) {
         * System.out.println("Initializing log4j with: " + log4jProp);
         * PropertyConfigurator.configure(log4jProp); } else {
         * System.err.println("*** " + log4jProp +
         * " file not found, so initializing log4j with BasicConfigurator");
         * BasicConfigurator.configure(); } }
         */
        super.init(config);
    }

    /**
     * @param request
     * @param response
     * @throws IOException
     */
    private void getUserSession(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.info("Received get user info request from: " + request.getRemoteHost());

        // Lấy thông tin người dùng được lưu trong session
        UserSession us = (UserSession) request.getSession().getAttribute(ApplicationConstants.SESSION_USER);

        // Phản hồi cho người dùng
        sendResponse(JsonConverter.getInstance().toJson(us));
    }

    /**
     * @param request
     * @param response
     * @throws IOException
     */
    private void authenticate(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.info("Received login request from: " + request.getRemoteHost());

        // Lấy username và password
        String username = request.getParameter(Parameter.USERNAME);
        String password = request.getParameter(Parameter.PASSWORD);

        // Tìm thông tin tài khoản trong cơ sở dữ liệu
        AccountBUS bus = new AccountBUS();
        Account acc = bus.getAccountByUsername(username);
        if (acc == null || !acc.getPassword().equals(password)) {
            logger.info("Login failed: " + request.getRemoteHost());
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Incorrect username and password");
        } else {
            logger.info(acc.getUsername() + " login success at: " + request.getRemoteHost());
            UserSession us = transformUserSession(request.getSession().getId(), acc);

            // Phản hồi cho người dùng
            sendResponse(JsonConverter.getInstance().toJson(us));

            // Đưa thông tin truy cập vào session
            request.getSession().setAttribute(ApplicationConstants.SESSION_USER, us);

            // Cập nhật thời gian đăng nhập.
            acc.setLastLoginDate(new Date());
            acc.setLasLoginIP(request.getRemoteHost());
            bus.save(acc);
        }
    }

    /**
     * 
     * @param request
     * @param response
     */
    private void signOut(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.info("Received logout request from: " + request.getRemoteHost());

        // Huỷ session hiện tại
        request.getSession().invalidate();
    }

    public UserSession transformUserSession(String sessionId, Account acc) {
        UserSession us = new UserSession();
        us.setId(acc.getId());
        us.setAvartar(acc.getTrainer().getAvatar());
        us.setPatronSaint(acc.getTrainer().getPatronSaint());
        us.setFirstName(acc.getTrainer().getFirstName());
        us.setLastName(acc.getTrainer().getLastName());
        if (acc.getTrainer().getCurrentCourse() != null) {
            us.setCurrentCourseId(acc.getTrainer().getCurrentCourse().getId());
            if (acc.getTrainer().getCurrentCourse().getYear() != null) {
                us.setYearId(acc.getTrainer().getCurrentCourse().getYear().getId());
            }
        }

        if (acc.getLastLoginDate() != null) {
            DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL);
            us.setLastLoginDate(formatter.format(acc.getLastLoginDate()));
        }

        us.setLastLoginIP(acc.getLasLoginIP());
        us.setLocked(acc.getLocked());
        // us.setSecurityCode();
        us.setUsername(acc.getUsername());

        return us;
    }

    @Override
    protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

    }

    @Override
    protected void fetch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (request.getParameter(Parameter.OPERATION_INFO).equals(Action.GET_CURRENT_USER)) {
            getUserSession(request, response);
        }
    }

    @Override
    protected void remove(HttpServletRequest request, HttpServletResponse response, boolean confirmation)
            throws ServletException, IOException {
        // TODO Auto-generated method stub

    }

    @Override
    protected void update(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        if (request.getParameter(Parameter.OPERATION_INFO).equals(Action.LOGIN)) {
            authenticate(request, response);
        } else if (request.getParameter(Parameter.OPERATION_INFO).equals(Action.LOGOUT)) {
            signOut(request, response);
        }
    }
}
